﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Globalization;
using System.ComponentModel;
using System.Dynamic;
using System.Data;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Threading;
using System.Windows.Threading;
using FinPlusWCFConnData;
using FinPlusCommon;
using log = Logger.Logger;
using u = FinPlusUtility.Utility;

namespace FinPlusWPFControls
{
    public class FinPlusColHelper : FinPlusControl
    {
        public override string Id { get; set; }
        public override string[] States { get { return new string[] { }; } }
        public override string[] TestStates { get { return new string[] { }; } }
        public override IFinPlusFunctions Model { get { return null; } }
        public override bool IsValid { get; set; }
        public override string ModelTest { get { return null; } }

        public Dictionary<string, CheckBox> HeaderCheckBoxsFilterbars { get; set; }

        private enum Params { Id, FunctionName, Tag, StringFormat, Type, InputMask, QuoteInstrument, BookedTrade, ClientGuid }
        private enum ColType { QuotePopup, FuncEditPopup, QuoteHit, ValueOnOff, ValueShift, ValueChange, ValueFormat, ValueTriState, ValueFunction, SelectLink, ComboLink, CheckBox, Exclude }

        private readonly FinPlusGroupGrid _grid;
        private readonly RoutedEventHandler _filterbarRemove, _filterbarAdd;
        private Dictionary<string, string> _quotePopupCols, _funcEditorPopupCols;
        private readonly Dictionary<string, ColMap> _colMap;
        private readonly ResourceDictionary _images, _other;
        private readonly List<string> _columnNames;
        private const double _defaultColWidth = 70;
        private readonly string _clientGuid;

        //constuct
        public FinPlusColHelper(FinPlusGroupGrid grid, RoutedEventHandler filterbarAdd, RoutedEventHandler filterbarRemove, string colTypes, string colIsEnabled, string colLinks, string colFormats)
        {
            _columnNames = new List<string>();
            _colMap = new Dictionary<string, ColMap>();
            _images = new ResourceDictionary{ Source = new Uri("pack://application:,,,/FinPlusWPFControls;component/Resource.Images.xaml", UriKind.RelativeOrAbsolute)};
            _other = new ResourceDictionary{ Source = new Uri("pack://application:,,,/FinPlusWPFControls;component/Resource.Other.xaml", UriKind.RelativeOrAbsolute) };
            _filterbarRemove = filterbarRemove;
            _filterbarAdd = filterbarAdd;
            _grid = grid;
            _clientGuid = u.Guid();
            HeaderCheckBoxsFilterbars = new Dictionary<string, CheckBox>();
            ColTypes(colTypes);
            ColIsEnabled(colIsEnabled);
            ColLinks(colLinks);
            ColFormats(colFormats);
        }

        //common control interface
        public override void Dock(object control, string dock)
        {
            IsValid = false;
            throw new NotImplementedException();
        }

        public override void Initialise()
        {

        }

        public override void CommandRouter(IFinPlusFunction func)
        {  
        
        }

        public override void Dispose()
        {
            try
            {
                throw new NotImplementedException();
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        //public
        public DataGridColumn GetColumn(string name, string type)
        {
            if (_columnNames.Contains(name)) return null;
            if (_quotePopupCols != null && (_quotePopupCols.ContainsValue(name) || _quotePopupCols.ContainsKey(name))) return null;
            if (_funcEditorPopupCols != null && (_funcEditorPopupCols.ContainsValue(name) || _funcEditorPopupCols.ContainsKey(name))) return null;

            var colMap = _colMap.ContainsKey(name) ? _colMap[name] : type == "Boolean" ? new ColMap() { ColType = ColType.CheckBox } : _colMap.ContainsKey("Default") ? _colMap["Default"] : new ColMap() { ColType = ColType.ValueFormat };

            DataGridColumn col = null;
            switch (colMap.ColType)
            {
                case ColType.QuotePopup: col = DataGridColQuotePopup(name, colMap.Link, colMap.IsEnabled); break;
                case ColType.FuncEditPopup: col = DataGridColFuncEditorPopup(name, colMap.Link, colMap.IsEnabled); break;
                case ColType.QuoteHit: col = DataGridColQuoteHit(name, colMap.StringFormat, colMap.Link, colMap.IsEnabled); break;
                case ColType.ValueOnOff: col = DataGridColValueOnOff(name, colMap.IsEnabled); break;
                case ColType.ValueShift: col = DataGridColValueShift(name, colMap.Link, colMap.StringFormat, colMap.InputMask, colMap.IsEnabled); break;
                case ColType.ValueChange: col = DataGridColValueChange(name, colMap.StringFormat); break;
                case ColType.ValueFormat: col = DataGridColValueFormat(name, colMap.StringFormat, colMap.InputMask, colMap.Type, colMap.IsEnabled, type.Equals("String")); break;
                case ColType.ValueTriState: col = DataGridColValueTriState(name, true); break;
                case ColType.ValueFunction: col = DataGridColValueFunction(name, colMap.IsEnabled); break;
                case ColType.SelectLink: col = DataGridColValueSelectBox(name, string.IsNullOrEmpty(colMap.Link) ? name : colMap.Link, colMap.IsEnabled); break;
                case ColType.ComboLink: col = DataGridColValueComboBox(name, string.IsNullOrEmpty(colMap.Link) ? name : colMap.Link, colMap.IsEnabled); break;
                case ColType.CheckBox: col = DataGridColValueCheckBox(name, colMap.IsEnabled); break;
            }

            _columnNames.Add(name);

            if (col == null) return null;

            col.SetValue(TagProperty, name);
            col.Width = _defaultColWidth;
            return col;
        }

        public void SetColState(DataGrid dataGrid, FinPlusColSelectBar colSelectBar, string states)
        {
            String.Join(";", dataGrid.Columns.Select(x => string.Format("{0},{1},{2},{3},{4}", x.GetValue(TagProperty), x.DisplayIndex, x.Width, x.Visibility == Visibility.Collapsed, x.SortDirection).ToArray()));
            foreach (var s in u.Split(states, ';'))
            {
                try
                {
                    var state = u.Split(s, ',');
                    if (string.IsNullOrEmpty(state[0])) continue;

                    var f = dataGrid.Columns.Where(c => c.GetValue(TagProperty).ToString() == state[0]);
                    if(f.Count() < 1) continue;
                    
                    var col = f.First();
                    col.DisplayIndex = int.Parse(state[1]);
                    var width = double.NaN;
                    
                    double.TryParse(state[2], out width);
                    col.Width = width; 
                    col.Visibility = (Visibility)Enum.Parse(typeof(Visibility), state[3]);
                    
                    if (colSelectBar != null) colSelectBar.AddButton(state[0], col.Visibility == Visibility.Collapsed);
                }
                catch (Exception e)
                {
                    log.Log(Logger.Level.Warning, e.Message, e);
                }
            }
        }

        public string GetColState(DataGrid dataGrid)
        {
            try
            {
                var s = dataGrid.Columns.OrderBy(x => x.DisplayIndex).Select(x => string.Format("{0},{1},{2},{3}", x.GetValue(TagProperty), x.DisplayIndex, x.Width, x.Visibility));
                return String.Join(";", s.ToArray());
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
                return null;
            }
        }

        //private
        private StackPanel HeaderColCheckBox(string name, string image = null)
        {
            var stackPanel = new StackPanel() { Tag = name, Orientation = Orientation.Horizontal };
            var header = HeaderCheckBoxsFilterbars[name] = new CheckBox() { Content = name, Tag = name, FlowDirection = FlowDirection.RightToLeft };
            header.Unchecked += _filterbarRemove;
            header.Checked += _filterbarAdd;
            if (image != null) 
                stackPanel.Children.Add(new Image() { Source = (BitmapImage)_images[image], Width = 9, Height = 9, VerticalAlignment = VerticalAlignment.Center });
            stackPanel.Children.Add(new TextBlock() { Text = " " });
            stackPanel.Children.Add(header);
            return stackPanel;
        }

        private StackPanel HeaderTextBlock(string name, string image = null)
        {
            var stackPanel = new StackPanel() { Tag = name, Orientation = Orientation.Horizontal };
            if (image != null) stackPanel.Children.Add(new Image() { Source = (BitmapImage)_images[image], Width = 9, Height = 9, VerticalAlignment = VerticalAlignment.Center });
            stackPanel.Children.Add(new TextBlock() { Text = name + " " });
            return stackPanel;
        }

        private DataGridColumn DataGridColQuotePopup(string name, string link, bool isEnabled)
        {
            if (isEnabled)
            {
                if (_quotePopupCols == null)
                {
                    _quotePopupCols = new Dictionary<string, string>();
                    _grid.DynFuncs.FunctionChanged += DataGridColQuote_Update;
                }
                _quotePopupCols[name] = link;
            }
            return null;
        }

        private DataGridColumn DataGridColFuncEditorPopup(string name, string link, bool isEnabled)
        {
            if (isEnabled)
            {
                if (_funcEditorPopupCols == null)
                {
                    _funcEditorPopupCols = new Dictionary<string, string>();
                    _grid.DynFuncs.FunctionChanged += DataGridBookedTrade_Update;
                }
                _funcEditorPopupCols[name] = link;
            }
            return null;
        }

        private DataGridColumn DataGridColQuoteHit(string name, string stringFormat, string link, bool isEnabled)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueQuoteHit));
            tb.SetBinding(FinPlusValueQuoteHit.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueQuoteHit.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueQuoteHit.QuoteProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueQuoteHit.PublishProperty, new Binding(link) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueQuoteHit.IsEnabledProperty, isEnabled);
            tb.SetValue(FinPlusValueQuoteHit.StringFormatProperty, stringFormat);
            tb.SetValue(FinPlusValueQuoteHit.GuidProperty, _clientGuid);

            var dt = new DataTemplate() { VisualTree = tb };

            return new DataGridTemplateColumn { Header = HeaderTextBlock(name, "SRotate"), ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellTemplate = dt, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueOnOff(string name, bool isEnabled)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueOnOffButton));
            tb.SetBinding(FinPlusValueOnOffButton.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueOnOffButton.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueOnOffButton.IsEnabledProperty, isEnabled);
            tb.SetBinding(FinPlusValueOnOffButton.IsCheckedProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            var et = new DataTemplate() { VisualTree = tb };

            var dt = ToggleImageCell(name, "OnOffToggleImage");
            
            return new DataGridTemplateColumn { Header = HeaderColCheckBox(name), ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellEditingTemplate = et, CellTemplate = dt, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueShift(string name, string link, string stringFormat, string inputMask, bool isEnabled)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueShiftTextBox));
            tb.SetBinding(FinPlusValueShiftTextBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueShiftTextBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueShiftTextBox.TextProperty, new Binding(name) { StringFormat = stringFormat, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueShiftTextBox.StepProperty, new Binding(link) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueShiftTextBox.IsEnabledProperty, isEnabled);
            tb.SetValue(FinPlusValueShiftTextBox.StringFormatProperty, stringFormat);
            tb.SetValue(FinPlusValueShiftTextBox.InputMaskProperty, new Regex(inputMask));
            var et = new DataTemplate() { VisualTree = tb };

            var dt = TextBlockCell(name, stringFormat, "Num");

            return new DataGridTemplateColumn { Header = HeaderTextBlock(name, "SUpDown"), ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellEditingTemplate = et, CellTemplate = dt, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueChange(string name, string stringFormat)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueChangeTextBox));
            tb.SetBinding(FinPlusValueChangeTextBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueChangeTextBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueChangeTextBox.TextProperty, new Binding(name) { StringFormat = stringFormat, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueChangeTextBox.StringFormatProperty, stringFormat);
       
            var dt = new DataTemplate() { VisualTree = tb };

            return new DataGridTemplateColumn { Header = name, ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellTemplate = dt, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueFormat(string name, string stringFormat, string inputMask, string type, bool isEnabled, bool hasFilter)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueFormatTextBox));
            tb.SetBinding(FinPlusValueFormatTextBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueFormatTextBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueFormatTextBox.TextProperty, new Binding(name) { StringFormat = stringFormat, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueFormatTextBox.IsEnabledProperty, isEnabled);
            tb.SetValue(FinPlusValueFormatTextBox.StringFormatProperty, stringFormat);
            tb.SetValue(FinPlusValueFormatTextBox.TypeProperty, type);
            tb.SetValue(FinPlusValueFormatTextBox.InputMaskProperty, string.IsNullOrEmpty(inputMask) ? null : new Regex(inputMask));
            var et = new DataTemplate() { VisualTree = tb };

            var dt = TextBlockCell(name, stringFormat, type);

            return new DataGridTemplateColumn { Header = hasFilter ? HeaderColCheckBox(name) : (object)name, CellEditingTemplate = et, CellTemplate = dt, ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, SortMemberPath = name, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueSelectBox(string name, string links, bool isEnabled)
        {
            var selectList = new List<string>();
            foreach (var link in u.Split(links, ','))
                selectList.AddRange(_grid.Structure.ToList(link));

            var tb = new FrameworkElementFactory(typeof(FinPlusValueSelectBox));
            tb.SetBinding(FinPlusValueSelectBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueSelectBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueSelectBox.TextProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueSelectBox.IsEnabledProperty, isEnabled);
            tb.SetValue(FinPlusValueSelectBox.ItemSourceProperty, selectList);
            var et = new DataTemplate() { VisualTree = tb};

            var dt = TextBlockCell(name);

            return new DataGridTemplateColumn { Header = HeaderColCheckBox(name, "SCreate"), ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellEditingTemplate = et, CellTemplate = dt, SortMemberPath = name, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueComboBox(string name, string links, bool isEnabled)
        {
            var selectList = new List<string>();
            foreach (var link in u.Split(links, ','))
                selectList.AddRange(_grid.Structure.ToList(link));

            var comboList = selectList.Select(f => new KeyValuePair<string, bool>(f, false)).ToDictionary(f => f.Key, f => f.Value);

            var tb = new FrameworkElementFactory(typeof(FinPlusValueComboBox));
            tb.SetBinding(FinPlusValueComboBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueComboBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueComboBox.TextProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueComboBox.IsEnabledProperty, isEnabled);
            tb.SetValue(FinPlusValueComboBox.ItemSourceProperty, comboList);
            var et = new DataTemplate() { VisualTree = tb };

            var dt = TextBlockCell(name);

            return new DataGridTemplateColumn { Header = HeaderColCheckBox(name, "SCreate"), ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CellEditingTemplate = et, CellTemplate = dt, SortMemberPath = name, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueCheckBox(string name, bool isEnabled)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueCheckBox));
            tb.SetBinding(FinPlusValueCheckBox.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueCheckBox.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueCheckBox.IsCheckedProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetValue(FinPlusValueCheckBox.IsEnabledProperty, isEnabled);
            var et = new DataTemplate() { VisualTree = tb };

            var dt = ToggleImageCell(name, "checkBoxToggleImage");

            return new DataGridTemplateColumn { Header = HeaderColCheckBox(name), CellEditingTemplate = et, CellTemplate = dt, ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, SortMemberPath = name, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueTriState(string name, bool hasFilter)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueTriState));
            tb.SetBinding(FinPlusValueTriState.IdProperty, new Binding(Params.Id.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueTriState.FunctionNameProperty, new Binding(Params.FunctionName.ToString()) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            tb.SetBinding(FinPlusValueTriState.StateProperty, new Binding(name) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

            var dt = new DataTemplate() { VisualTree = tb };
            return new DataGridTemplateColumn { Header = hasFilter ? HeaderColCheckBox(name) : (object)name, CellTemplate = dt, ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, SortMemberPath = name, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataGridColumn DataGridColValueFunction(string name, bool isEnabled)
        {
            var tb = new FrameworkElementFactory(typeof(FinPlusValueFunction));
            tb.SetValue(FinPlusValueFunction.IsEnabledProperty, isEnabled);
            tb.SetBinding(FinPlusValueFunction.FunctiontProperty, new Binding(name) { Mode = BindingMode.OneWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
            var et = new DataTemplate() { VisualTree = tb };

            var dt = ButtonImageCell("funcButtonImage");

            return new DataGridTemplateColumn { Header = name, CellEditingTemplate = et, CellTemplate = dt, ClipboardContentBinding = new Binding(name) { Mode = BindingMode.OneWay }, CanUserSort = true, Width = _defaultColWidth };
        }

        private DataTemplate TextBlockCell(string name, string stringFormat = null, string type = null)
        {
            var factory = new FrameworkElementFactory(typeof(TextBlock));
            
            var b = new Binding(name);
            if (stringFormat != null)
                b.StringFormat = stringFormat;

            if (type != null && type.Equals("Num"))
                factory.SetValue(Image.StyleProperty, (Style)_other["numTextBlock"]);
            
            factory.SetBinding(TextBlock.TextProperty, b);

            return new DataTemplate() { VisualTree = factory };
        }

        private DataTemplate ToggleImageCell(string name, string imageStyle)
        {
            var factory = new FrameworkElementFactory(typeof(Image));

            var b = new Binding(name);

            factory.SetBinding(Image.TagProperty, b);
            factory.SetValue(Image.StyleProperty, (Style)_other[imageStyle]);

            return new DataTemplate() { VisualTree = factory };
        }

        private DataTemplate ButtonImageCell(string imageStyle)
        {
            var factory = new FrameworkElementFactory(typeof(Image));

            factory.SetValue(Image.StyleProperty, (Style)_other[imageStyle]);

            return new DataTemplate() { VisualTree = factory };
        }

        private void FuncEditorPopUp(IFinPlusFuncDynamic funcDynamic, string propertyName)
        {
            try
            {
                object trade, id;
                if (funcDynamic.TryGetObject(Params.Id.ToString(), out id) && _grid.GetPermission(Params.QuoteInstrument.ToString(), Params.Id.ToString(), id.ToString()).CanWrite && funcDynamic.TryGetObject(propertyName, out trade))
                    FinPlusWindow.Open(Function.FromString(trade.ToString()), "FuncEdit", Env );
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        private void QuotePopUp(IFinPlusFuncDynamic funcDynamic, string propertyName)
        {
            try
            {
                object quoteRequest, id;
                if (funcDynamic.TryGetObject(Params.Id.ToString(), out id) && funcDynamic.TryGetObject(propertyName, out quoteRequest))
                {
                    var quote = Function.FromString(quoteRequest.ToString());
                    var guid = quote[Params.ClientGuid.ToString()].ToString();
                    if ((guid.Equals(_clientGuid) || string.IsNullOrEmpty(guid)) && GetPermission(Params.QuoteInstrument.ToString(), Params.Id.ToString(), quote.Get(Params.Id.ToString()).Value).CanWrite)
                    {
                        FinPlusValueQuotePopup.Show(quote, funcDynamic, id.ToString(), _quotePopupCols[propertyName], _clientGuid);
                        //((MediaPlayer)this.FindResource("SoundBlop")).Play();
                        System.Media.SystemSounds.Beep.Play();
                    }
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Warning, e.Message, e);
            }
        }

        private void ColTypes(string colTypes)
        {
            try
            {
                if (!string.IsNullOrEmpty(colTypes))
                {
                    foreach (var colType in u.Split(colTypes, ';'))
                    {
                        var cols = u.Split(colType, ':');
                        var colTypeEnum = (ColType)Enum.Parse(typeof(ColType), cols[0]);
                        if (cols.Count() > 1)
                            foreach (var colName in u.Split(cols[1], ','))
                                _colMap[colName] = new ColMap() { ColType = colTypeEnum };
                    }
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        private void ColIsEnabled(string colIsEnabled)
        {
            try
            {
                if (string.IsNullOrEmpty(colIsEnabled)) return;

                foreach (var colReadOnly in u.Split(colIsEnabled, ','))
                {
                    if (!_colMap.ContainsKey(colReadOnly))
                        _colMap[colReadOnly] = new ColMap() { ColType = ColType.ValueFormat };
                    _colMap[colReadOnly].IsEnabled = true;
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        private void ColLinks(string colLinks)
        {
            try
            {
                if (string.IsNullOrEmpty(colLinks)) return;

                foreach (var colLink in u.Split(colLinks, ';'))
                {
                    var link = u.Split(colLink, ':');
                    if (link.Count() < 0) continue;

                    foreach (var colName in u.Split(link[1], ','))
                    {
                        if (!_colMap.ContainsKey(colName))
                            _colMap[colName] = new ColMap() { ColType = ColType.ValueFormat };
                        var colMap = _colMap[colName];
                        colMap.Link = colMap.Value = link[0];
                    }
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        private void ColFormats(string colFormats)
        {
            try
            {
                if (string.IsNullOrEmpty(colFormats)) return;

                foreach (var colFormat in u.Split(colFormats, ';'))
                {
                    var s = u.Split(colFormat, ':');
                    foreach (var colName in u.Split(s[1], ','))
                    {
                        if (!_colMap.ContainsKey(colName)) _colMap[colName] = new ColMap() { ColType = ColType.ValueFormat };
                        var colMap = _colMap[colName];
                        var format = (Hashtable)_grid.FindResource(s[0]);
                        colMap.StringFormat = format[Params.StringFormat.ToString()].ToString();
                        colMap.Type = format[Params.Type.ToString()].ToString();
                        colMap.InputMask = format[Params.InputMask.ToString()].ToString();
                    }
                }
            }
            catch (Exception e)
            {
                log.Log(Logger.Level.Error, Id, Config, e.Message, e);
            }
        }

        //evants
        private void DataGridColQuote_Update(object sender, PropertyChangedEventArgs a) { if (_quotePopupCols.ContainsKey(a.PropertyName)) QuotePopUp((IFinPlusFuncDynamic)sender, a.PropertyName); }
        private void DataGridBookedTrade_Update(object sender, PropertyChangedEventArgs a) { if (_funcEditorPopupCols.ContainsKey(a.PropertyName))  FuncEditorPopUp((IFinPlusFuncDynamic)sender, a.PropertyName); }

        //private class
        private class ColMap 
        { 
            public ColType ColType; 
            public string Link = string.Empty;  
            public string  StringFormat = string.Empty;
            public string InputMask = string.Empty;
            public string Type = string.Empty;
            public string Value;  
            public bool IsEnabled;
        }
    }
}
